﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using EnCor.Security.Claims;

namespace EnCor.Security
{
    public class SecurityCenter : ISecurityCenter
    {
        #region Private Members

        private AuthenticationCenter _AuthenticationCenter;

        private AuthorizationCenter _AuthorizationCenter;

        private IdentityMapperCollection _IdentityMappers;



        internal void Config(SecurityConfig config)
        {
            // IdentityMappers
            List<IIdentityMapper> mappers = new List<IIdentityMapper>();
            IdentityMapperFactory identityMapperFactory = new IdentityMapperFactory();
            foreach (IdentityMapperConfig mapperConfig in config.IdentityMappers)
            {

                IIdentityMapper mapper = identityMapperFactory.Create(null, mapperConfig);
                mapper.Name = mapperConfig.Name;
                mappers.Add(mapper);
            }
            _IdentityMappers = new IdentityMapperCollection(mappers);

            // Authentication
            _AuthenticationCenter = new AuthenticationCenter(config.AuthenticationConfig, _IdentityMappers);

            // Authorization
            _AuthorizationCenter = new AuthorizationCenter(config.AuthorizationConfig, _IdentityMappers);

            //SecurityContext.Init(new CommonSecurityContextProvider(_AuthenticationCenter, _AuthorizationCenter));
        }
        #endregion

        #region Public Members


        

        public AuthenticateToken Authenticate(Credential credential)
        {
            try
            {
                var token = _AuthenticationCenter.Authenticate(credential);
                if (token == null)
                {
                    return null;
                }
                Thread.CurrentPrincipal = new EnCorPrincipal(token.Identity);
                SecurityContext.Current = new SecurityContext(new EnCorPrincipal(token.Identity), _AuthorizationCenter.GetUserClaimSet(token.Identity));
                return token;
            }
            catch (AuthenticationException ex)
            {
                throw;
            }
        }

        public void Logoff()
        {
            _AuthenticationCenter.LogoffCurrentUser();
        }

        #endregion

        #region Static Members
        #endregion

        internal void InitializeSecurityContext()
        {
            EnCorIdentity identity = _AuthenticationCenter.AuthenticateCurrentUser();
            if (identity != null)
            {
                Thread.CurrentPrincipal = new EnCorPrincipal(identity);
                SecurityContext.Current = new SecurityContext(new EnCorPrincipal(identity), _AuthorizationCenter.GetUserClaimSet(identity));
            }
        }


    }
}
